package com.dhcc.bpm.modules.scf.service.impl;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dhcc.bpm.common.segmentId.LocalCacheIdGenerator;
import com.dhcc.bpm.common.utils.StringUtils;
import com.dhcc.bpm.modules.scf.dto.ScfPaymentInfoDTO;
import com.dhcc.bpm.modules.scf.entity.ScfOperationLogInfo;
import com.dhcc.bpm.modules.scf.entity.ScfPaymentInfo;
import com.dhcc.bpm.modules.scf.enumUtil.ScfOperationLogInfoEnum;
import com.dhcc.bpm.modules.scf.mapper.*;
import com.dhcc.bpm.modules.scf.service.IScfFileAttachmentInfoService;
import com.dhcc.bpm.modules.scf.service.IScfOperationLogInfoService;
import com.dhcc.bpm.modules.scf.service.IScfPaymentInfoService;
import com.dhcc.bpm.modules.scf.util.ExcelUtil;
import com.dhcc.bpm.modules.scf.util.MD5Utils;
import com.dhcc.bpm.modules.scf.util.OBSUtil;
import com.dhcc.bpm.modules.scf.vo.ScfFileAttachmentInfoVO.ScfFileAttachmentInfoVO;
import com.dhcc.bpm.modules.scf.vo.ScfInvoiceInfoVO.ScfGetInvoiceListVO;
import com.dhcc.bpm.modules.scf.vo.ScfPaymentInfoVO.ScfGetPaymentDetailsVO;
import com.dhcc.bpm.modules.scf.vo.ScfPaymentInfoVO.ScfGetPaymentListVO;
import com.dhcc.bpm.modules.scf.vo.ScfRecyclingInInfoVO.ScfGetRecyclingInDetailsVO;
import com.dhcc.bpm.modules.scf.vo.ScfRenewableInInfoVO.ScfGetRenewableInDetailsVO;
import com.dhcc.bpm.modules.system.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 支付信息表Service实现类
 */
@Service
@Slf4j
public class ScfPaymentInfoServiceImpl extends ServiceImpl<ScfPaymentInfoMapper, ScfPaymentInfo> implements IScfPaymentInfoService {
    /**
     * 文件附件service接口
     */
    @Autowired
    private IScfFileAttachmentInfoService scfFileAttachmentInfoService;
    /**
     * id生成器
     */
    @Autowired
    private LocalCacheIdGenerator localCacheIdGenerator;
    /**
     * 操作日志service接口
     */
    @Autowired
    private IScfOperationLogInfoService scfOperationLogInfoService;

    /**
     * 主体信息mapper接口
     */
    @Autowired
    private ScfSubjectBasicInfoMapper scfSubjectBasicInfoMapper;
    /**
     * 再生入库单mapper接口
     */
    @Autowired
    private ScfRenewableInInfoMapper scfRenewableInInfoMapper;
    /**
     * 利废入库单mapper接口
     */
    @Autowired
    private ScfRecyclingInInfoMapper scfRecyclingInInfoMapper;

    @Autowired
    private ScfInvoiceInfoMapper scfInvoiceInfoMapper;

    /**
     * 用户信息service接口
     */
    @Autowired
    private IUserService userService;
    /**
     * obs对象存储工具类
     */
    @Autowired
    private OBSUtil obsUtil;

    /**
     * 支付回单自定义分页查询
     *
     * @param page
     * @param scfPaymentInfo
     * @return
     */


    @Override
    public IPage<ScfGetPaymentListVO> selectScfPaymentInfoPage(IPage<ScfGetPaymentListVO> page, ScfPaymentInfoDTO scfPaymentInfo) {
//        初始化值
        baseMapper.updateRemainAmountWs();
        baseMapper.updateRemainAmountLfrk();
        baseMapper.updateRemainAmountZsrk();
//进化值
        baseMapper.updateRemainAmountbyPaymentNumWs();
        baseMapper.updateRemainAmountbyPaymentNumLfrk();
        baseMapper.updateRemainAmountbyPaymentNumZsrk();


        // 查询支付回单分页列表数据
        List<ScfGetPaymentListVO> scfGetPaymentListVOS = baseMapper.selectScfPaymentInfoPage(page, scfPaymentInfo);
        // 如果列表数据有记录
        if (scfGetPaymentListVOS.size() != 0) {
            for (ScfGetPaymentListVO scfGetPaymentListVO : scfGetPaymentListVOS) {

                // 根据用户id查询用户名称，重新赋值登记人字段
                List<Long> ids = new ArrayList<>();
                ids.add(Long.valueOf(scfGetPaymentListVO.getRecorder()));

                scfGetPaymentListVO.setRecorder(userService.selectUserNameByIds(ids).get(0));



//                给以默认值 给支付的剩余金额 1是收款 ，收款对应在再生
                if("1".equals( scfGetPaymentListVO.getPaymentType() )    ){
                    scfGetPaymentListVO.setNotHexiaoAmount( scfGetPaymentListVO.getLfrkRemainAmount());
                }else {//2是付款  再生入库是付款
                    scfGetPaymentListVO.setNotHexiaoAmount( scfGetPaymentListVO.getZsrkRemainAmount());
                }


                // 通过支付回单的使用金额和剩余金额判断使用状态
                if (scfGetPaymentListVO.getAmount().subtract(scfGetPaymentListVO.getNotHexiaoAmount()) .compareTo(BigDecimal.ZERO)  ==0 ) { // 如果支付回单的交易金额等于剩余金额
                    // 设置使用状态为暂时未使用
                    scfGetPaymentListVO.setUseSts("0");
                }
                if  ( scfGetPaymentListVO.getAmount().subtract(scfGetPaymentListVO.getNotHexiaoAmount()) .compareTo(BigDecimal.ZERO)  >0 ) { // 如果支付回单的剩余金额大于0且不等于交易金额
                    // 设置使用状态为部分使用
                    scfGetPaymentListVO.setUseSts("1");
                }
                if (scfGetPaymentListVO.getNotHexiaoAmount().compareTo(BigDecimal.ZERO) == 0) { // 如果支付回单的剩余金额为0
                    // 设置使用状态为全部使用
                    scfGetPaymentListVO.setUseSts("2");
                }
                scfGetPaymentListVO.setVisualAmount(scfGetPaymentListVO.getNotHexiaoAmount() );

                scfGetPaymentListVO.setNotKaipiaoAmount( scfGetPaymentListVO.getRemainAmount());
                if("1".equals(scfGetPaymentListVO.getIsWithInvoice()  ) &&   scfGetPaymentListVO.getNotKaipiaoAmount().compareTo( BigDecimal.ZERO) ==0){
                    scfGetPaymentListVO.setIsWithInvoice( "2");
                }

            }
        }



        return page.setRecords(scfGetPaymentListVOS);
    }

    /**
     * 详情查询
     *
     * @param scfPaymentInfo
     * @return
     */
    @Override
    public ScfGetPaymentDetailsVO getDetail(ScfPaymentInfoDTO scfPaymentInfo) {
        // 查询详情信息
/*        if(StringUtils.isNotEmpty( scfPaymentInfo.getRowId() )){

        }*/
        ScfGetPaymentDetailsVO detail = baseMapper.getDetail(scfPaymentInfo.getRowId());


        if (detail != null) {
            // 获取与文件附件表关联的id
            String rowId = detail.getRowId();
            // 查询关联的附件信息
            List<ScfFileAttachmentInfoVO> scfFileAttachmentInfoVOS = scfFileAttachmentInfoService.selectAllByAssociationId(rowId);
            // 设置文件附件数据
            detail.setFileAttachmentInfoVOS(scfFileAttachmentInfoVOS);
            // 根据用户id查询用户名称，重新赋值登记人字段
            List<Long> ids = new ArrayList<>();
            ids.add(Long.valueOf(detail.getRecorder()));
            detail.setRecorder(userService.selectUserNameByIds(ids).get(0));
            // 获取支付回单对应的入库单
            String paymentNum = detail.getPaymentNum();
            // 获取对应的再生入库单
            List<String> renewableInByPaymentNum = baseMapper.getRenewableInByPaymentNum(paymentNum);
            List<ScfGetRenewableInDetailsVO> scfGetRenewableInDetailsVOList = new ArrayList<>();
            if (renewableInByPaymentNum != null) {
                for (String renewableInByPayment : renewableInByPaymentNum) {
                    String rowIdByRenewableInNum = scfRenewableInInfoMapper.selectRowIdByRenewableInNum(renewableInByPayment);
                    ScfGetRenewableInDetailsVO scfRenewableInInfoMapperDetails = scfRenewableInInfoMapper.getDetails(rowIdByRenewableInNum);
                    scfGetRenewableInDetailsVOList.add(scfRenewableInInfoMapperDetails);
                }
                detail.setScfGetRenewableInDetailsVOList(scfGetRenewableInDetailsVOList);
            }


            // 获取对应的利废入库单
            List<String> recyclingInByPaymentNum = baseMapper.getRecyclingInByPaymentNum(paymentNum);
            List<ScfGetRecyclingInDetailsVO> scfGetRecyclingInDetailsVOList = new ArrayList<>();
            if (recyclingInByPaymentNum != null) {
                for (String recyclingInByPayment : recyclingInByPaymentNum) {
                    String selectRowIdByRecyclingInNum = scfRecyclingInInfoMapper.selectRowIdByRecyclingInNum(recyclingInByPayment);
                    ScfGetRecyclingInDetailsVO scfRecyclingInInfoMapperDetails = scfRecyclingInInfoMapper.getDetails(selectRowIdByRecyclingInNum);
                    scfGetRecyclingInDetailsVOList.add(scfRecyclingInInfoMapperDetails);
                }
            }
            detail.setScfGetRecyclingInDetailsVOList(scfGetRecyclingInDetailsVOList);


            List<ScfGetInvoiceListVO> scfGetInvoiceListVOS = scfInvoiceInfoMapper.queryByScfGetInvoiceListVOByPaymentRowId(scfPaymentInfo.getRowId() ,detail.getPaymentNum());

            detail.setScfInvoiceInfoDTOList(scfGetInvoiceListVOS);

        }
        return detail;
    }

    /**
     * 新增支付回单
     *
     * @param scfPaymentInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean savePaymentInfo(ScfPaymentInfoDTO scfPaymentInfo) throws Exception {
        // 录入开始首先判断该支付回单是否已录入
        if (baseMapper.selectRowIdBypaymentNum(scfPaymentInfo.getPaymentNum()) != null) {
            // 根据发票号码查询到了对应的记录rowId--则认为该支付回单已录入
            throw new Exception("支付回单：" + scfPaymentInfo.getPaymentNum() + "已录入，请勿重复录入！");
        }
        // 生成日期
        SimpleDateFormat date = new SimpleDateFormat("YYYYMMdd");
        String formatdate = date.format(new Date());
        // 生成时间
        SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
        String formTime = timeFormat.format(new Date());

        // 开始补充对象字段start
        // 设置初始使用金额==回单金额
        scfPaymentInfo.setRemainAmount(scfPaymentInfo.getAmount());
        // 设置初始使用状态为暂未使用(0:暂未使用，1：部分使用，2：全部使用)
        scfPaymentInfo.setUseSts("0");
        // 设置初始关联发票状态（0:暂未关联，1：部分关联，2：完成关联）
        scfPaymentInfo.setIsWithInvoice("0");
        // 设置记录编号
        scfPaymentInfo.setRowId("ZF" + MD5Utils.md5(  scfPaymentInfo.getPaymentNum()) );
        // 设置登记日期
        scfPaymentInfo.setRecordDate(formatdate);
        // 设置登记时间
        scfPaymentInfo.setRecordTime(formTime);
        // 信息补充完成
        boolean isSave = save(scfPaymentInfo);
        List<String> fujianIds = scfPaymentInfo.getRowIds();
        // 设置支付文件存放路径
        String path = "ZF" + "/" + "ZF" + MD5Utils.md5(  scfPaymentInfo.getPaymentNum())  + "/";

            if (!fujianIds.isEmpty()  && isSave) {
                    for (String fujianRowId : fujianIds) {
                        // 根据文件id获取文件的临时objectKey
                        String objectKeyOfTemp = scfFileAttachmentInfoService.getFilePath(fujianRowId, null);
                        // 截取文件的名称
                        String extractFileName = obsUtil.extractFileName(objectKeyOfTemp);
                        // 拼接正式的objectKey
                        String objectKey = path + extractFileName;
                        // 将上传的附件从临时文件夹复制到正式文件夹下
                        obsUtil.copyFile(objectKey, objectKeyOfTemp);
                        scfFileAttachmentInfoService.updateFilePath(fujianRowId, objectKey);
                    }

            // 补充对象字段结束end
            scfFileAttachmentInfoService.batchUpdateField(fujianIds, "ZF" + MD5Utils.md5(  scfPaymentInfo.getPaymentNum()));

        }
        // 记录操作日志
        // 生成日期时间
        SimpleDateFormat datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = datetime.format(new Date());
        ScfOperationLogInfo scfOperationLogInfo = new ScfOperationLogInfo();
        // 根据用户id查询用户名称，重新赋值登记人字段
        List<Long> ids = new ArrayList<>();
        ids.add(Long.valueOf(scfPaymentInfo.getRecorder()));
        scfOperationLogInfo.setRecorder(userService.selectUserNameByIds(ids).get(0));
        scfOperationLogInfo.setOperationModule(ScfOperationLogInfoEnum.PAYMENT.getOperation());
        scfOperationLogInfo.setOperationFunction("支付信息维护");
        scfOperationLogInfo.setOperationType(ScfOperationLogInfoEnum.ADD.getOperation());
        scfOperationLogInfo.setOperationContent("新增一条支付信息，交易流水号：" + scfPaymentInfo.getPaymentNum());
        scfOperationLogInfo.setRecordDate(formattedDateTime);
        // 判断支付回单信息是否新增成功
        if (isSave) {
            // 成功则同时记录操作日志
            scfOperationLogInfoService.saveOperationLogInfo(scfOperationLogInfo);
        }
        return isSave;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int bachSavePaymentInfo(List<ScfPaymentInfo> scfPaymentInfos, String operatorId) {
        List<ScfPaymentInfo> scfPaymentInfoList = new ArrayList<>();
        List<ScfOperationLogInfo> scfOperationLogInfoList = new ArrayList<>();
        for (ScfPaymentInfo scfPaymentInfo : scfPaymentInfos) {
            // 设置登记人ID
            scfPaymentInfo.setRecorder(operatorId);
            // 设置初始剩余金额为交易金额
            scfPaymentInfo.setRemainAmount(scfPaymentInfo.getAmount());
            // 设置初始使用状态为未使用：0
            scfPaymentInfo.setUseSts("0");
            // 设置默认是否关联发票为：暂未关联0，
            scfPaymentInfo.setIsWithInvoice("0");
            // 回单类型
            String paymentType = scfPaymentInfo.getPaymentType();
            if (paymentType != null) {
                switch (paymentType) {
                    case "收款回单":
                        // 执行与 value1 匹配的代码块
                        scfPaymentInfo.setPaymentType("1");
                        break;
                    case "付款回单":
                        // 执行与 value2 匹配的代码块
                        scfPaymentInfo.setPaymentType("2");
                        break;
                    // 可以有更多的 case 分支
                    default:
                        // 如果没有任何 case 匹配，则执行 default 代码块
                        break;
                }
            }
            // 是否预付款
            String isAdvancePayment = scfPaymentInfo.getIsAdvancePayment();
            if (isAdvancePayment != null) {
                switch (isAdvancePayment) {
                    case "是":
                        // 执行与 value1 匹配的代码块
                        scfPaymentInfo.setIsAdvancePayment("1");
                        break;
                    case "否":
                        // 执行与 value2 匹配的代码块
                        scfPaymentInfo.setIsAdvancePayment("0");
                        break;
                    // 可以有更多的 case 分支
                    default:
                        // 如果没有任何 case 匹配，则执行 default 代码块
                        break;
                }
            }

            SimpleDateFormat date = new SimpleDateFormat("YYYYMMdd");
            String formatdate = date.format(new Date());
            // 生成时间
            SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
            String formTime = timeFormat.format(new Date());
            // 生成ROW_ID
//            String rowId = "ZF" + localCacheIdGenerator.nextId() + formTime;
            // 开始补充对象字段start
            // 设置初始使用金额==回单金额
            scfPaymentInfo.setRemainAmount(scfPaymentInfo.getAmount());
            // 设置初始使用状态为暂未使用(0:暂未使用，1：部分使用，2：全部使用)
            scfPaymentInfo.setUseSts("0");
            // 设置初始关联发票状态（0:暂未关联，1：部分关联，2：完成关联）
            scfPaymentInfo.setIsWithInvoice("0");
            // 设置记录编号
            scfPaymentInfo.setRowId( "ZF" + MD5Utils.md5(  scfPaymentInfo.getPaymentNum()) );
            // 设置登记日期
            scfPaymentInfo.setRecordDate(formatdate);
            // 设置登记时间
            scfPaymentInfo.setRecordTime(formTime);
            // 录入开始首先判断该支付回单是否已录入
            if (baseMapper.selectRowIdBypaymentNum(scfPaymentInfo.getPaymentNum()) == null) {
                scfPaymentInfoList.add(scfPaymentInfo);
                // 记录操作日志
                // 生成日期时间
                SimpleDateFormat datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String formattedDateTime = datetime.format(new Date());
                ScfOperationLogInfo scfOperationLogInfo = new ScfOperationLogInfo();
                // 根据用户id查询用户名称，重新赋值登记人字段
                List<Long> ids = new ArrayList<>();
                ids.add(Long.valueOf(scfPaymentInfo.getRecorder()));
                scfOperationLogInfo.setRecorder(userService.selectUserNameByIds(ids).get(0));
                scfOperationLogInfo.setOperationModule(ScfOperationLogInfoEnum.PAYMENT.getOperation());
                scfOperationLogInfo.setOperationFunction("支付信息维护");
                scfOperationLogInfo.setOperationType(ScfOperationLogInfoEnum.ADD.getOperation());
                scfOperationLogInfo.setOperationContent("新增一条支付信息，交易流水号：" + scfPaymentInfo.getPaymentNum());
                scfOperationLogInfo.setRecordDate(formattedDateTime);
                scfOperationLogInfoList.add(scfOperationLogInfo);
            }
        }
        boolean saveBatch = saveBatch(scfPaymentInfoList);
        if (saveBatch) {
            scfOperationLogInfoService.bachSaveOperationLogInfo(scfOperationLogInfoList);
        }
        return scfPaymentInfoList.size();
    }

    /**
     * 更新支付回单信息
     *
     * @param scfPaymentInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updatePaymentInfo(ScfPaymentInfoDTO scfPaymentInfo) {
        String rowId = scfPaymentInfo.getRowId();
        List<String> rowIds = scfPaymentInfo.getRowIds();
        // 获取支付回单面值金额
        BigDecimal amount = scfPaymentInfo.getAmount();
        // 判断单子类型-1.收款=利废入库-2.付款=再生入库
        String paymentType = scfPaymentInfo.getPaymentType();
        if (paymentType.equals("1")) {
            // 获取利废入库与支付回单关联关系计算新的剩余金额
            BigDecimal recyclingUseAmountByPaymentNum = baseMapper.getRecyclingUseAmountByPaymentNum(scfPaymentInfo.getPaymentNum());
            // 判空处理，如果为 null，则置为 BigDecimal.ZERO
            recyclingUseAmountByPaymentNum = (recyclingUseAmountByPaymentNum == null) ? BigDecimal.ZERO : recyclingUseAmountByPaymentNum;
            BigDecimal result = amount.subtract(recyclingUseAmountByPaymentNum);
            scfPaymentInfo.setRemainAmount(result);
        } else if (paymentType.equals("2")) {
            // 获取再生入库与支付回单关联关系计算新的剩余金额
            BigDecimal renewableUseAmountByPaymentNum = baseMapper.getRenewableUseAmountByPaymentNum(scfPaymentInfo.getPaymentNum());
            // 判空处理，如果为 null，则置为 BigDecimal.ZERO
            renewableUseAmountByPaymentNum = (renewableUseAmountByPaymentNum == null) ? BigDecimal.ZERO : renewableUseAmountByPaymentNum;
            BigDecimal result = amount.subtract(renewableUseAmountByPaymentNum);
            scfPaymentInfo.setRemainAmount(result);
        }

        // 更新支付回单信息
        boolean update = updateById(scfPaymentInfo);
        // 设置支付文件存放路径
        String path = "ZF" + "/" + rowId + "/";
        if (rowId != null) {
            if (!rowIds.isEmpty()) {
                // 取消旧文件与记录关联
                scfFileAttachmentInfoService.updataFiledNull(rowId);
                // 给上传的新文件添加关联编号
                scfFileAttachmentInfoService.batchUpdateField(rowIds, rowId);
                for (String fileRowId : rowIds) {
                    // 根据文件id获取文件的临时objectKey
                    String objectKeyOfTemp = scfFileAttachmentInfoService.getFilePath(fileRowId, null);
                    // 截取文件的名称
                    String extractFileName = obsUtil.extractFileName(objectKeyOfTemp);
                    // 拼接正式的objectKey
                    String objectKey = path + extractFileName;
                    // 将更新后的附件文件从临时目录转移至正式目录下
                    obsUtil.copyFile(objectKey, objectKeyOfTemp);
                    scfFileAttachmentInfoService.updateFilePath(fileRowId, objectKey);
                }
            }
        }
        // 记录操作日志
        // 生成日期时间
        SimpleDateFormat datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = datetime.format(new Date());
        // 生成日期
        SimpleDateFormat date = new SimpleDateFormat("YYYYMMdd");
        String formatdate = date.format(new Date());
        // 生成时间
        SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
        String formTime = timeFormat.format(new Date());
        ScfOperationLogInfo scfOperationLogInfo = new ScfOperationLogInfo();
        // 根据用户id查询用户名称，重新赋值登记人字段
        List<Long> ids = new ArrayList<>();
        ids.add(Long.valueOf(scfPaymentInfo.getRecorder()));
        scfOperationLogInfo.setRecorder(userService.selectUserNameByIds(ids).get(0));
        scfOperationLogInfo.setOperationModule(ScfOperationLogInfoEnum.PAYMENT.getOperation());
        scfOperationLogInfo.setOperationFunction("支付信息维护");
        scfOperationLogInfo.setOperationType(ScfOperationLogInfoEnum.UPDATE.getOperation());
        scfOperationLogInfo.setOperationContent("更新一条支付信息，交易流水号：" + scfPaymentInfo.getPaymentNum());
        scfOperationLogInfo.setRecordDate(formattedDateTime);
        // 判断支付回单更新是否成功
        if (update) {
            // 成功则同步记录操作日志记录
            scfOperationLogInfoService.saveOperationLogInfo(scfOperationLogInfo);
        }
        return update;
    }

    /**
     * @param operatorId 批量上传导入
     * @param file
     * @return
     * @throws IOException
     */
    @Override
    public List<ScfPaymentInfo> batchSaveScfPaymentInfo(String operatorId, MultipartFile file) throws IOException {
        // 获取文件的Base64编码
        byte[] fileBytes = file.getBytes();
        // 解析excel文件获取数据集合
        List<ScfPaymentInfo> scfPaymentInfos = ExcelUtil.readExcel(fileBytes, ScfPaymentInfo.class, "支付信息", 3);
        log.info("数据集合为：{}", scfPaymentInfos);
        return scfPaymentInfos;
    }

    @Override
    public Boolean deleteByIds(String[] ids) {
        return this.baseMapper.deleteByIds(ids);
    }
}
